package org.one.afternoon.utils;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import io.swagger.v3.core.util.Json;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringEscapeUtils;
import org.one.afternoon.domain.EdgeData;
import org.one.afternoon.domain.Swim;
import org.one.afternoon.domain.dto.DetectionsDto;
import org.one.afternoon.domain.dto.Result2BackDto;
import org.one.afternoon.domain.dto.Swim2BackDto;
import org.one.afternoon.domain.dto.SwimmingDto;
import org.one.afternoon.provider.detection_ai.DetectionProvider;
import org.one.afternoon.service.EdgeService;
import org.one.afternoon.service.SwimmingService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.*;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@EnableScheduling
@Component
@PropertySource("classpath:application.yml")
@Slf4j
public class ScheduleJob {

    @Value("${IMAGE_LOCATION:spring.servlet.multipart.location}")
    private String filePath;

    @Value("${AI_IP_ADDRESS}")
    private String ip;

    private static final String TEST_JSON = "{\n    \"source_image\": \"/app/img/000148.jpg\",\n    \"target_image\": \"/docker/img_out/000148.jpg\",\n    \"detections\": [\n        {\n            \"category\": \"swimmers\",\n            \"confidence\": 0.66,\n            \"box\": {\n                \"top\": 140,\n                \"left\": 459,\n                \"bottom\": 177,\n                \"right\": 515\n            }\n        },\n        {\n            \"category\": \"swimmers\",\n            \"confidence\": 0.62,\n            \"box\": {\n                \"top\": 269,\n                \"left\": 104,\n                \"bottom\": 315,\n                \"right\": 150\n            }\n        }\n    ],\n    \"swimmers\": 2,\n    \"sus_swimmers\": 0,\n    \"passerby\": 0\n}";
    private static final String EXP = "{\n    \"source_image\": \"/app/img/000148.jpg\",\n    \"target_image\": \"/docker/img_out/000148.jpg\",\n    \"detections\": [\n        {\n            \"category\": \"swimmers\",\n            \"confidence\": 0.66,\n            \"box\": {\n                \"top\": 140,\n                \"left\": 459,\n                \"bottom\": 177,\n                \"right\": 515\n            }\n        },\n        {\n            \"category\": \"swimmers\",\n            \"confidence\": 0.62,\n            \"box\": {\n                \"top\": 269,\n                \"left\": 104,\n                \"bottom\": 315,\n                \"right\": 150\n            }\n        }\n    ],\n    \"swimmers\": 2,\n    \"sus_swimmers\": 0,\n    \"passerby\": 0\n}";

    private static final EdgeService edgeService = ApplicationContextUtil.getBean(EdgeService.class);

    private static final SwimmingService swimmingService = ApplicationContextUtil.getBean(SwimmingService.class);

    /**
     * 创建一个有关检测新图片的定时任务
     */
    @Scheduled(fixedRate = 5000)
    private void directoryChecker() {
        log.info("ScheduleJob conduct...");

        // 轮询数据库，检索新图片
        List<EdgeData> newImages = edgeService.findNewImage();

        // 判断是否为空，为空不进行处理
        if (newImages != null && !newImages.isEmpty()) {

            // 遍历Image列表
            for (EdgeData newImage : newImages) {

                // 获取每个图片的路径
                String path = edgeService.getFileUrl(newImage.getFilePath());
                if (path != null) {

                    // 得到路径后调用AI接口，返回一个SwimmingDto对象
                    SwimmingDto swimmingDto = edgeService.detectObject(ip, path);
                    // 若得到的结果为null，则不做处理并打印日志至控制台
                    if (swimmingDto != null) {

                        // 获取AI处理后的图片路径
                        File result = new File(swimmingDto.getTargetImage());
                        try {
                            // 上传图片至minio
                            edgeService.uploadBucket(new FileInputStream(result), result.getName(), null);
                        } catch (FileNotFoundException e) {
                            log.error(e.getMessage());
                        }

                        // 将图片推送到后台管理系统
                        Result2BackDto result2BackDto = edgeService.pushImage(new Swim2BackDto(swimmingDto.getSourceImage(), swimmingDto.getTargetImage(), swimmingDto.getSwimmers(), swimmingDto.getSusSwimmers(), swimmingDto.getPasserBy(), newImage.getLat(), newImage.getLon()));

                        if (result2BackDto.getCode() == 200) {
                            log.info("推送成功,将数据转存到数据库...");
                            // 统计识别分类的人数，并获得一个Swim对象
                            Swim swim = statistic(swimmingDto, newImage.getId());

                            // 将结果保存数据库
                            boolean save = swimmingService.save(swim);

                            if (save) {

                                //若保存成功则将目标图片的状态置为1
                                edgeService.updateStatus(newImage.getId());
                                log.info("Swimming-data save Successfully！");
                            } else {
                                log.error("Swimming-data save Failure！");
                            }
                        }
                    } else {
                        log.error("Swimming-data is NULL！");
                    }
                }
            }
        }
    }

    public static boolean hasFilesInDirectory(Path directoryPath) {
        try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
            return stream.iterator().hasNext();
        } catch (Exception e) {
            // 处理异常，例如打印堆栈跟踪或记录日志
            e.printStackTrace();
            return false;
        }
    }


    /**
     * 统计swimming/noSwimming/swimmingReady
     *
     * @param swimmingDto AI传回的数据
     * @param edgeId      对应的图片Id
     * @return 整理好的Swim对象
     */
    private static Swim statistic(SwimmingDto swimmingDto, int edgeId) {
        Swim swim = new Swim();
        swim.setNoSwimming(swimmingDto.getPasserBy());
        swim.setSwimming(swimmingDto.getSwimmers());
        swim.setSwimmingReady(swimmingDto.getSusSwimmers());
        swim.setEdgeId(edgeId);
        swim.setOriginalFileName(swimmingDto.getSourceImage());
        swim.setResultFileName(swimmingDto.getTargetImage());
        return swim;
    }

    /**
     * 去除JSON字符串中的空格、回车等特殊字符
     *
     * @param str JSON字符串
     * @return 处理后的JSON字符串
     */
    public static String replaceBlank(String str) {
        String dest = "";
        if (str != null) {
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            dest = m.replaceAll("");
        }
        return dest;
    }
}
